home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / ae_14.zip / AE3.PAS < prev    next >
Pascal/Delphi Source File  |  1991-03-08  |  24KB  |  589 lines

  1. unit AE3 ;
  2.  
  3. {$B-}
  4. {$I-}
  5. {$S+}
  6. {$V-}
  7.  
  8. interface
  9.  
  10. uses Crt,Dos,AE0,AE1,AE2 ;
  11.  
  12. procedure EnterString (var S:string; Prompt:string ; MaxLength:byte ;
  13.                        CapsLock:boolean ; AlphaOnly:boolean) ;
  14. procedure EnterWord (var W:word ; Prompt:string ; MinValue,MaxValue:word) ;
  15. procedure EnterBoolean (var B:boolean ; Prompt:string ) ;
  16. procedure SaveFile (Wsnr:byte) ;
  17. function GetKeyNr : word ;
  18. function Answer (question:string) : boolean ;
  19. function Choose (Choices:string) : char ;
  20.  
  21. implementation
  22.  
  23. {-----------------------------------------------------------------------------}
  24. { Prompts the user to enter a string on the bottom line of the screen, with   }
  25. { maximum length <MaxLength>. Parameters CapsLock and AlphaOnly instruct the  }
  26. { procedure to convert lower case characters to upper case, and to accept     }
  27. { only alphanumeric characters, respectively. Pressing Escape will restore    }
  28. { the old value of S.                                                         }
  29. {-----------------------------------------------------------------------------}
  30.  
  31. procedure EnterString (var S:string; Prompt:string ; MaxLength:byte ;
  32.                        CapsLock:boolean ; AlphaOnly:boolean) ;
  33.  
  34. var OldS : string ;
  35.     OldXpos,OldYpos : byte ;
  36.     OldCursorType : byte ;
  37.     i : byte ;
  38.     Key : word ;
  39.     Start,VisibleLength : byte ;
  40.  
  41. begin
  42. { replace CR/LF pairs in string with CRLFalias }
  43. repeat i := Pos (CR+LF,S) ;
  44.        if i > 0
  45.           then begin
  46.                S[i] := CRLFalias[1] ;
  47.                S[i+1] := CRLFalias[2] ;
  48.                end ;
  49. until i = 0 ;
  50. OldXpos := WhereX ;
  51. OldYpos := WhereY ;
  52. OldCursorType := GetCursor ;
  53. SetCursor (Config.Setup.CursorType) ;
  54. OldS := S ;
  55. Start := 1 ;
  56. VisibleLength := ColsOnScreen - Length(Prompt) - 1 ;
  57. SetBottomLine (Prompt+Copy(S,Start,VisibleLength)) ;
  58. CursorTo (Length(Prompt)+1,25) ;
  59. Key := GetKeyNr ;
  60. if (Key < 256) or (Key = CtrlReturnKey)
  61.    then S := '' ;
  62. i := 1 ;
  63. repeat case Key of
  64.             264 {Bksp}    : if i > 1
  65.                                then begin
  66.                                     if Copy(S,i-1,2) = CRLFalias
  67.                                        then begin
  68.                                             Dec (i,2) ;
  69.                                             Delete (S,i,2) ;
  70.                                             end
  71.                                        else begin
  72.                                             Dec (i) ;
  73.                                             Delete (S,i,1) ;
  74.                                             end ;
  75.                                     end
  76.                                else WarningBeep ;
  77.             EscapeKey     : S := OldS ;
  78.             32..126       : if Length(S) < MaxLength
  79.                                then begin
  80.                                     if CapsLock
  81.                                        then Insert (UpCase(Chr(Key)),S,i)
  82.                                        else Insert (Chr(Key),S,i) ;
  83.                                     Inc (i) ;
  84.                                     end
  85.                                else WarningBeep ;
  86.             1..31,
  87.             127..255      : if (not AlphaOnly) and (Length(S) < MaxLength)
  88.                                then begin
  89.                                     Insert (Chr(Key),S,i) ;
  90.                                     Inc (i) ;
  91.                                     end
  92.                                else WarningBeep ;
  93.             CtrlReturnKey : if (not AlphaOnly) and (Length(S) < (MaxLength-1))
  94.                                then begin
  95.                                     Insert (CRLFalias,S,i) ;
  96.                                     Inc (i,2)
  97.                                     end
  98.                                else WarningBeep ;
  99.             327 {Home}    : i := 1 ;
  100.             335 {End}     : i := Length (S) + 1 ;
  101.             331 {Left}    : begin
  102.                             if i > 1
  103.                                then begin
  104.                                     if (Copy(S,i-2,2) = CRLFalias) and (i > 2)
  105.                                        then Dec (i,2)
  106.                                        else Dec (i) ;
  107.                                     end ;
  108.                             end ;
  109.             333 {Right}   : if i <= Length (S)
  110.                                then begin
  111.                                     if Copy(S,i,2) = CRLFalias
  112.                                        then Inc (i,2)
  113.                                        else Inc (i) ;
  114.                                     end ;
  115.             339 {Del}     : if Copy(S,i,2) = CRLFalias
  116.                                then Delete (S,i,2)
  117.                                else Delete (S,i,1) ;
  118.             end ; {of case}
  119.        if i > (Start+VisibleLength)
  120.           then Start := i - VisibleLength
  121.           else begin
  122.                if Start > i
  123.                   then Start := i ;
  124.                end ;
  125.        SetBottomLine (Prompt+Copy(S,Start,VisibleLength)) ;
  126.        CursorTo (Length(Prompt)+1+i-Start,25) ;
  127.        if (Key <> ReturnKey) and (Key <> EscapeKey) then Key := GetKeyNr ;
  128. until (Key = ReturnKey) or (Key = EscapeKey) ;
  129. { replace CRLFalias in string with CR/LF pairs }
  130. repeat i := Pos (CRLFalias,S) ;
  131.        if i > 0
  132.           then begin
  133.                S[i] := CR ;
  134.                S[i+1] := LF ;
  135.                end ;
  136. until i = 0 ;
  137. EscPressed := (Key = EscapeKey) ;
  138. SetBottomLine ('') ;
  139. CursorTo (OldXpos,OldYpos) ;
  140. SetCursor (OLdCursorType) ;
  141. end ;
  142.  
  143. {-----------------------------------------------------------------------------}
  144. { Prompts the user to enter a numeric value. If a string is entered that can  }
  145. { not be interpreted as a numeric value, or if the value is not within the    }
  146. { limits MinValue..MaxValue, a beep is given and the procedure is repeated.   }
  147. { Pressing Escape will restore the old value of W.                            }
  148. {-----------------------------------------------------------------------------}
  149.  
  150. procedure EnterWord (var W:word ; Prompt:string ; MinValue,MaxValue:word) ;
  151.  
  152. var S:string ;
  153.     Code : integer ;
  154.     OK : boolean ;
  155.  
  156. begin
  157. Str (W,S) ;
  158. repeat EnterString (S,Prompt,5,False,True) ;
  159.        Val (S,W,Code) ;
  160.        OK := (Code = 0) and (W >= MinValue) and (W <= MaxValue) ;
  161.        if not OK then WarningBeep ;
  162. until OK ;
  163. end ;
  164.  
  165. {-----------------------------------------------------------------------------}
  166. { Prompts the user to enter a boolean value. The current value is displayed,  }
  167. { and can be changed with the space bar or the cursor keys. Pressing Return   }
  168. { stores the value and exits, and the Y and N keys may be used for entering   }
  169. { the desired value directly. Pressing Escape will restore the old value.     }
  170. {-----------------------------------------------------------------------------}
  171.  
  172. procedure EnterBoolean (var B:boolean ; Prompt:string ) ;
  173.  
  174. var OldB : boolean ;
  175.     OldCursorType : byte ;
  176.     Key : word ;
  177.  
  178. begin
  179. OldCursorType := GetCursor ;
  180. SetCursor (Inactive) ;
  181. OldB := B ;
  182. repeat if B
  183.           then SetBottomLine (Prompt+' Yes')
  184.           else SetBottomLine (Prompt+' No') ;
  185.        Key := GetKeyNr ;
  186.        case Key of
  187.             32,328,331,333,336 : B := not B ;
  188.             78,110             : begin
  189.                                  B := False ;
  190.                                  Key := ReturnKey ;
  191.                                  end ;
  192.             89,121             : begin
  193.                                  B := True ;
  194.                                  Key := ReturnKey ;
  195.                                  end ;
  196.             EscapeKey          : B := OldB ;
  197.             ReturnKey          : ;
  198.             else                 WarningBeep ;
  199.             end ;
  200. until (Key = ReturnKey) or (Key = EscapeKey) ;
  201. EscPressed := (Key = EscapeKey) ;
  202. SetBottomLine ('') ;
  203. SetCursor (OldCursorType) ;
  204. end ;
  205.  
  206. {-----------------------------------------------------------------------------}
  207. { Saves the file in workspace <Wsnr> to disk. If there is no name yet,        }
  208. { the user is prompted for one.                                               }
  209. {-----------------------------------------------------------------------------}
  210.  
  211. procedure SaveFile (Wsnr:byte) ;
  212.  
  213. var F : file ;
  214.     Counter : word ;
  215.     DotPos : byte ;
  216.     BAKfilename : PathStr ;
  217.     OldStatusLine : ScreenBlockPtr ;
  218.  
  219. begin
  220. { save contents of statusline }
  221. SaveArea (1,LinesOnScreen,ColsOnScreen,LinesOnScreen,OldStatusLine) ;
  222. with Workspace[Wsnr] do
  223.      begin
  224.      EscPressed := False ;
  225.      if Length(Name) = 0
  226.         then begin
  227.              EnterString (Name,'Saving file. Filename: ',79,True,True) ;
  228.              if Length(Name) = 0
  229.                 then EscPressed := True
  230.                 else if Wildcarded(Name)
  231.                         then begin
  232.                              ErrorMessage (16) ;
  233.                              EscPressed := True ;
  234.                              end
  235.                         else Name := FExpand (Name) ;
  236.              end ;
  237.      if not EscPressed
  238.         then begin
  239.              Message ('Saving file '+Name) ;
  240.              if (Config.Setup.MakeBAKfile) and (Exists(Name))
  241.                 then begin
  242.                      { determine name of backup file }
  243.                      DotPos := Pos ('.',Name) ;
  244.                      if DotPos = 0
  245.                         then BAKfilename := Name + '.BAK'
  246.                         else BAKfilename := Copy(Name,1,DotPos)+'BAK' ;
  247.                      { delete old backup file if present }
  248.                      if Exists (BAKfilename)
  249.                         then begin
  250.                              Assign (F,BAKfilename) ;
  251.                              Erase (F) ;
  252.                              end ;
  253.                      { rename file to backup file }
  254.                      Assign (F,Name) ;
  255.                      Rename (F,BAKfilename) ;
  256.                      end ;
  257.              Assign (F,Name) ;
  258.              Rewrite (F,BufferSize) ;
  259.              CheckDiskError ;
  260.              if DiskError = 0
  261.                 then begin
  262.                      { save contents of buffer to file }
  263.                      BlockWrite (F,Buffer^,1) ;
  264.                      CheckDiskError ;
  265.                      Close (F) ;
  266.                      if DiskError = 0
  267.                         then { save was successful }
  268.                              ChangesMade := False ;
  269.                      end ;
  270.              GetTime (LastTimeSaved[1],LastTimeSaved[2],
  271.                       LastTimeSaved[3],LastTimeSaved[4]) ;
  272.              MessageRead := True ;
  273.              end ;
  274.      end ; { of with }
  275. { restore status line }
  276. RestoreArea (1,LinesOnScreen,ColsOnScreen,LinesOnScreen,OldStatusLine) ;
  277. end ;
  278.  
  279. {-----------------------------------------------------------------------------}
  280. { Displays a table with the entire IBM character set, from which the user     }
  281. { can then make a choice, using the cursor and Return keys. Pressing Escape   }
  282. { will return a value of 279. Cursor shape and position and screen contents   }
  283. { are saved, and restored on exit.                                            }
  284. {-----------------------------------------------------------------------------}
  285.  
  286. function GetKeyFromTable : word ;
  287.  
  288. var OldAttr,OldXpos,OldYpos,OldCursorType,KeyNr,Counter : byte ;
  289.     OldDisplayContents : ScreenBlockPtr ;
  290.     ScrEl : ScreenElement ;
  291.     SelectKey : word ;
  292.  
  293. begin
  294. OldXpos := WhereX ;
  295. OldYpos := WhereY ;
  296. OldCursorType := GetCursor ;
  297. OldAttr := TextAttr ;
  298. TextAttr := ScreenColorArray[Config.Setup.ScreenColors].NormAttr ;
  299. SaveArea (7,2,74,21,OldDisplayContents) ;
  300. SetCursor (Inactive) ;
  301. { put empty table on screen }
  302. PutFrame (7,2,74,21,Quasi3DFrame) ;
  303. ClearArea (8,3,73,20) ;
  304. ScrEl.Attribute := TextAttr ;
  305. { fill table }
  306. for Counter := 0 to 255 do
  307.     begin
  308.     ScrEl.Contents := Chr(Counter) ;
  309.     DisplayPtr^[4+(Counter div 32)*2,9+(Counter mod 32)*2] := word(ScrEl) ;
  310.     end ;
  311. KeyNr := 0 ;
  312. repeat GotoXY (9,20) ; Write ('ASCII value: ',KeyNr:3) ;
  313.        { show selected character }
  314.        with ScreenColorArray[Config.Setup.ScreenColors] do
  315.             ScrEl.Attribute := BlockAttr ;
  316.        ScrEl.Contents := Chr(KeyNr) ;
  317.        DisplayPtr^[4+(KeyNr div 32)*2,9+(KeyNr mod 32)*2] := word(ScrEl) ;
  318.        { read a key from the keyboard }
  319.        SelectKey := ReadKeyNr ;
  320.        { hide previously selected character }
  321.        ScrEl.Attribute := TextAttr ;
  322.        ScrEl.Contents := Chr(KeyNr) ;
  323.        DisplayPtr^[4+(KeyNr div 32)*2,9+(KeyNr mod 32)*2] := word(ScrEl) ;
  324.        case SelectKey of
  325.             328       : { up     } Dec (KeyNr,32) ;
  326.             336       : { down   } Inc (KeyNr,32) ;
  327.             331       : { left   } Dec (KeyNr) ;
  328.             333       : { right  } Inc (KeyNr) ;
  329.             371       : { ^left  } Dec (KeyNr,8) ;
  330.             372       : { ^right } Inc (KeyNr,8) ;
  331.             ReturnKey : ;
  332.             EscapeKey : ;
  333.             else        WarningBeep ;
  334.             end ; { of case }
  335.        ScrEl.Attribute := TextAttr ;
  336.        ScrEl.Contents := Chr(KeyNr) ;
  337.        DisplayPtr^[4+(KeyNr div 32)*2,9+(KeyNr mod 32)*2] := word(ScrEl) ;
  338. until (SelectKey = ReturnKey) or (SelectKey = EscapeKey) ;
  339. RestoreArea (7,2,74,21,OldDisplayContents) ;
  340. TextAttr := OldAttr ;
  341. GotoXY (OldXpos,OldYpos) ;
  342. SetCursor (OldCursorType) ;
  343. if SelectKey = EscapeKey
  344.    then GetKeyFromTable := 279 { alt-I }
  345.    else GetKeyFromTable := KeyNr ;
  346. end ;
  347.  
  348. {-----------------------------------------------------------------------------}
  349. { Displays help screens containing the key definitions                        }
  350. { Cursor shape and position and screen contents are saved, and                }
  351. { restored on exit.                                                           }
  352. {-----------------------------------------------------------------------------}
  353.  
  354. procedure DisplayHelp ;
  355.  
  356. var OldDisplayContents : ScreenBlockPtr ;
  357.     OldXpos,OldYpos,OldCursorType : byte ;
  358.  
  359. begin
  360. OldXpos := WhereX ;
  361. OldYpos := WhereY ;
  362. OldCursorType := GetCursor ;
  363. SetCursor (Inactive) ;
  364. SaveArea (1,1,ColsOnScreen,LinesOnScreen,OldDisplayContents) ;
  365. ClearArea (1,1,ColsOnScreen,NrOfTextLines) ;
  366. Writeln ('          ┌────────────────────┬─────────────────┐') ;
  367. Writeln ('          │ NORMAL KEY         │ CONTROL+KEY     │') ;
  368. Writeln ('┌─────────┼────────────────────┼─────────────────┤') ;
  369. Writeln ('│ ─      │ PREVIOUS CHARACTER │ PREVIOUS WORD   │') ;
  370. Writeln ('│ ─      │ NEXT CHARACTER     │ NEXT WORD       │') ;
  371. Writeln ('│        │ PREVIOUS LINE      │                 │') ;
  372. Writeln ('│        │ NEXT LINE          │                 │') ;
  373. Writeln ('│ Home    │ BEGIN OF LINE      │ BEGIN OF SCREEN │') ;
  374. Writeln ('│ End     │ END OF LINE        │ END OF SCREEN   │') ;
  375. Writeln ('│ Page Up │ PREVIOUS SCREEN    │ BEGIN OF TEXT   │') ;
  376. Writeln ('│ Page Dn │ NEXT SCREEN        │ END OF TEXT     │') ;
  377. Writeln ('└─────────┴────────────────────┴─────────────────┘') ;
  378. Writeln ;
  379. Writeln ('┌───────────┬───────────────────────────────┐') ;
  380. Writeln ('│ Insert    │ TOGGLE INSERT/OVERWRITE MODE  │') ;
  381. Writeln ('│ Delete    │ REMOVE CHARACTER UNDER CURSOR │') ;
  382. Writeln ('│ Backspace │ REMOVE PREVIOUS CHARACTER     │') ;
  383. Writeln ('└───────────┴───────────────────────────────┘') ;
  384. Pause ;
  385. if not EscPressed
  386.    then
  387.      begin
  388.      ClearArea (1,1,ColsOnScreen,NrOfTextLines) ;
  389.      Writeln ('      ┌─────────────┬───────────────────────────────┐') ;
  390.      Writeln ('      │ NORMAL KEY  │ SHIFT+KEY                     │') ;
  391.      Writeln ('┌─────┼─────────────┼───────────────────────────────┤') ;
  392.      Writeln ('│ F1  │ HELP        │ SETUP                         │') ;
  393.      Writeln ('│ F2  │ SAVE FILE   │ WRITE TO FILE                 │') ;
  394.      Writeln ('│ F3  │ LOAD FILE   │ INSERT FILE                   │') ;
  395.      Writeln ('│ F4  │ FIND *      │ FIND & REPLACE *              │') ;
  396.      Writeln ('│ F5  │ PUT MARK    │ ERASE MARK                    │') ;
  397.      Writeln ('│ F6  │ CUT BLOCK   │ DELETE BLOCK                  │') ;
  398.      Writeln ('│ F7  │ COPY BLOCK  │ COMPARE BLOCK TO PASTE BUFFER │') ;
  399.      Writeln ('│ F8  │ PASTE BLOCK │ PRINT BLOCK                   │') ;
  400.      Writeln ('│ F9  │ NEXT WINDOW │ PREVIOUS WINDOW               │') ;
  401.      Writeln ('│ F10 │ DOS COMMAND │                               │') ;
  402.      Writeln ('└─────┴─────────────┴───────────────────────────────┘') ;
  403.      Writeln ;
  404.      Writeln (' *: FIND/REPLACE OPTIONS') ;
  405.      Writeln ;
  406.      Writeln ('      I = IGNORE CASE') ;
  407.      Writeln ('      N = NO QUERY DURING REPLACE') ;
  408.      Writeln ('      R = REVERSE DIRECTION') ;
  409.      Pause ;
  410.      end ; { of if }
  411. if not EscPressed
  412.    then
  413.      begin
  414.      ClearArea (1,1,ColsOnScreen,NrOfTextLines) ;
  415.      Writeln ('┌─────────┬───────────────────────────┐') ;
  416.      Writeln ('│ ALT+KEY │ ACTION                    │') ;
  417.      Writeln ('├─────────┼───────────────────────────┤') ;
  418.      Writeln ('│ 1..9,0  │ PLAY MACRO NR 1,..9,10    │') ;
  419.      Writeln ('│ A       │ SWITCH TO WINDOW A        │') ;
  420.      Writeln ('│ C       │ CENTER LINE               │') ;
  421.      Writeln ('│ D       │ DEFINE KEYBOARD MACRO     │') ;
  422.      Writeln ('│ E       │ EJECT PRINTER PAGE        │') ;
  423.      Writeln ('│ F       │ FORMAT PARAGRAPH          │') ;
  424.      Writeln ('│ G       │ GET SAVED POSITION        │') ;
  425.      Writeln ('│ I       │ IBM CHAR.SET (ASCII TABLE)│') ;
  426.      Writeln ('│ J       │ JUSTIFY LINE RIGHT        │') ;
  427.      Writeln ('│ L       │ DELETE LINE               │') ;
  428.      Writeln ('│ M       │ MATCH BRACKETS ({[<>]})   │') ;
  429.      Writeln ('│ N       │ NEW (CLEAR BUFFER)        │') ;
  430.      Writeln ('│ P       │ PRINT ENTIRE FILE         │') ;
  431.      Writeln ('│ R       │ REPEAT LAST FIND/REPLACE  │') ;
  432.      Writeln ('│ S       │ SAVE POSITION             │') ;
  433.      Writeln ('│ T       │ TOGGLE CASE IN BLOCK      │') ;
  434.      Writeln ('│ W       │ DELETE WORD FORWARD       │') ;
  435.      Writeln ('│ X       │ EXIT PROGRAM              │') ;
  436.      Writeln ('└─────────┴───────────────────────────┘') ;
  437.      Pause ;
  438.      end ; { of if }
  439. RestoreArea (1,1,ColsOnScreen,LinesOnScreen,OldDisplayContents) ;
  440. GotoXY (OldXpos,OldYpos) ;
  441. SetCursor (OldCursorType) ;
  442. end ;
  443.  
  444. {-----------------------------------------------------------------------------}
  445. { Returns a key number, read from a macro if one is running, or from the      }
  446. { keyboard otherwise. The procedure takes care of displaying ASCII tables,    }
  447. { help screens and of storing the number of the key in the macro space        }
  448. { if a macro is being defined.                                                }
  449. {-----------------------------------------------------------------------------}
  450.  
  451. function GetKeyNr : word ;
  452.  
  453. var KeyNr : word ;
  454.     Hrs,Mins,Secs,Sec100s,TimePassed : word ;
  455.     WsNr : byte ;
  456.  
  457. begin
  458. if MacroStackpointer <> Inactive
  459.    then begin
  460.         { get keynumber from macro }
  461.         with Config do
  462.              begin
  463.              Keynr := Macro.Contents[MacroStack[MacroStackpointer].Macronr,
  464.                                MacroStack[MacroStackpointer].Index] ;
  465.              repeat { set Index to next keynumber in macro sequence }
  466.                     Inc (MacroStack[MacroStackpointer].Index) ;
  467.                     if MacroStack[MacroStackpointer].Index >
  468.                        Macro.Length[MacroStack[MacroStackpointer].Macronr]
  469.                        then begin
  470.                             { macro finished, decrease stackpointer }
  471.                             Dec (MacroStackpointer) ;
  472.                             end ;
  473.              until (MacroStackpointer = Inactive) or
  474.                    (MacroStack[MacroStackpointer].Index <=
  475.                     Macro.Length[MacroStack[MacroStackpointer].Macronr]) ;
  476.              end ; { of with }
  477.         end
  478.    else begin
  479.         { get keynumber from keyboard }
  480.         repeat GetTime (Hrs,Mins,Secs,Sec100s) ;
  481.               for WsNr := 1 to NrOfWorkspaces do
  482.                   with Workspace[WsNr] do
  483.                        begin
  484.                        { calculate time since last save of file in Workspace }
  485.                        if LastTimeSaved[1] > Hrs
  486.                           then TimePassed := 60 * (24+Hrs-LastTimeSaved[1])
  487.                           else TimePassed := 60 * (Hrs-LastTimeSaved[1]) ;
  488.                        if LastTimeSaved[2] > Mins
  489.                           then Dec (TimePassed,LastTimeSaved[2]-Mins)
  490.                           else Inc (TimePassed,Mins-LastTimeSaved[2]) ;
  491.                        if LastTimeSaved[3] > Secs
  492.                           then Dec (TimePassed) ;
  493.                        if (Config.Setup.SaveInterval <> Inactive) and
  494.                           (TimePassed >= Config.Setup.SaveInterval) and
  495.                           ChangesMade and
  496.                           (Length(Name) <> 0)
  497.                           then SaveFile(Wsnr) ;
  498.                        end ; { of with }
  499.         until KeyPressed ;
  500.         repeat KeyNr := ReadKeyNr ;
  501.                if KeyNr = 315 { F1 } then DisplayHelp ;
  502.                if KeyNr = 279 { alt-I } then KeyNr := GetKeyFromTable ;
  503.         until (KeyNr <> 315) and (KeyNr <> 279) ;
  504.         if Config.Setup.Keyclick
  505.            then begin
  506.                 Sound(440) ;
  507.                 Delay(2) ;
  508.                 NoSound ;
  509.                 end ;
  510.         if (MacroDefining <> Inactive) and (KeyNr <> 288 { alt-D })
  511.            then begin
  512.                 if Config.Macro.Length[MacroDefining] = MaxMacroLength
  513.                    then begin
  514.                         { macro too long }
  515.                         ErrorMessage (6) ;
  516.                         MacroDefining := Inactive ;
  517.                         end
  518.                    else begin
  519.                         { add keynumber to macro }
  520.                         Inc (Config.Macro.Length[MacroDefining]) ;
  521.                         Config.Macro.Contents[MacroDefining,
  522.                                  Config.Macro.Length[MacroDefining]] := KeyNr ;
  523.                         end ;
  524.                 end ;
  525.         end ; { of if }
  526. GetKeyNr := KeyNr ;
  527. MessageRead := True ;
  528. end ;
  529.  
  530. {-----------------------------------------------------------------------------}
  531. { Puts a question on the bottom screen line and then waits until the Y, N or  }
  532. { Escape key is pressed. The Y key produces a True result, the N and Escape   }
  533. { a False function result.                                                    }
  534. {-----------------------------------------------------------------------------}
  535.  
  536. function Answer (Question:string) : boolean ;
  537.  
  538. var Key : word ;
  539.     OldX,OldY,OldCursorType : byte ;
  540.  
  541. begin
  542. OldX := WhereX ;
  543. OldY := WhereY ;
  544. OldCursorType := GetCursor ;
  545. Message (Question+' (Y/N) ') ;
  546. CursorTo (Length(Question)+8,LinesOnScreen) ;
  547. SetCursor (Config.Setup.CursorType) ;
  548. repeat Key := GetKeyNr
  549. until (Key in [78,89,110,121]) or
  550.       (Key = EscapeKey) ;
  551. Answer := (Key = 89) or (Key = 121) ;
  552. EscPressed := (Key = EscapeKey) ;
  553. CursorTo (OldX,OldY) ;
  554. SetCursor (OldCursorType) ;
  555. end ;
  556.  
  557. {-----------------------------------------------------------------------------}
  558. { Displays the Choices string on the bottom screen line, and waits for the    }
  559. { user to make a choice, which is made by pressing a letter key which,        }
  560. { converted to upper case, also occurs in the string. This key is then        }
  561. { returned as the function result. Exit by pressing Escape is also possible.  }
  562. {-----------------------------------------------------------------------------}
  563.  
  564. function Choose (Choices:string) : char ;
  565.  
  566. var Key : word ;
  567.     KeyC : char ;
  568.     Valid : boolean ;
  569.  
  570. begin
  571. SetBottomLine (Choices) ;
  572. repeat Key := GetKeyNr ;
  573.        if Key < 256
  574.           then KeyC := UpCase(Chr(Key))
  575.           else KeyC := #0 ;
  576.        Valid := ((KeyC in ['A'..'Z']) and (Pos(KeyC,Choices) <> 0)) or
  577.                 (Key = EscapeKey) ;
  578.        if not Valid
  579.           then WarningBeep ;
  580. until Valid ;
  581. EscPressed := (Key = EscapeKey) ;
  582. Choose := KeyC ;
  583. Message ('') ;
  584. end ;
  585.  
  586. {-----------------------------------------------------------------------------}
  587.  
  588. end.
  589.